package com.zhoukx.nio;

import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;

import javax.lang.model.type.ArrayType;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Arrays;

/**
 * 前面我们讲的读写操作，都是通过一个Buffer 完成的，NIO 还支持 通过多个Buffer (即 Buffer 数组) 完成读写操作，即 Scattering 和 Gathering
 * Scattering:将数据写入到buffer时,可以采用buffer数组,一次写入(分散)
 * Gathering: 从buffer读取数据时,可以采用buffer数组,依次读取
 */
public class ScatteringAndGathering {

    public static void main(String[] args) throws IOException {
        // 使用serverSockertChannel 和SocketChannel 网络
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        InetSocketAddress inetSocketAddress = new InetSocketAddress(9011);

        // 绑定端口到socket,并启动
        serverSocketChannel.socket().bind(inetSocketAddress);

        // 创建buffer数组
        ByteBuffer[] byteBuffers = new ByteBuffer[2];
        byteBuffers[0] = ByteBuffer.allocate(5);
        byteBuffers[1] = ByteBuffer.allocate(3);

        // 等待客户端连接
        SocketChannel socketChannel = serverSocketChannel.accept();
        // 假定从客户端接收8字节
        int messageLength = 8;

        while (true) {
            int byteRead = 0;

            while (byteRead < messageLength) {
                long read = socketChannel.read(byteBuffers);
                // 累计读取数据
                byteRead += read;
                System.out.println("byteRead: " + byteRead);
                // 使用流打印,看当前的这个buffer的position和limt
                Arrays.asList(byteBuffers).stream().map(buffer -> "position=" + buffer.position() + "" +
                        ",limit =" + buffer.limit()).forEach(System.out::println);

            }
            // 将所有buffer进行filp
            Arrays.asList(byteBuffers).forEach(byteBuffer -> byteBuffer.flip());

            // 将读出来的数据显示到客户端
            long byteWrite = 0;
            while (byteWrite < messageLength) {
                long write = socketChannel.write(byteBuffers);
                byteWrite += write;
            }

            // 将所有的buffer进行clear
            Arrays.asList(byteBuffers).forEach(byteBuffer -> byteBuffer.clear());
            System.out.println("byteRead= " + byteRead + " byteWrite= " + byteWrite + " messagelength= " + messageLength);
        }
    }
}
